/* $RCSFile: PortalCRMModuleControl.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/ADNCRM.Core/UI/WebControls/PortalCRMModuleControl.cs $
 * $log$
 * Revision 19 2011/01/21 17:51:08  christian.surieux
 *   Recover from Sony move files updated in 11/2010 were not in Source Control
 * Revision 6 2010/08/06 19:56:30  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.Diagnostics;
using System.Data;
using System.Reflection;
using System.ComponentModel;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.Caching;
using System.Text;
using System.Xml;

using AddonNice.UI;
using AddonNice.UI.DataTypes;
using AddonNice.UI.WebControls;
using AddonNice.Helpers;
using AddonNice.Security;
using AddonNice.Configuration;
using AddonNice.Configuration.Settings;
using AddonNice.Diagnostics;
using AddonNice.Design;
using AddonNice.CRMWrapper;

using Trace2    =   System.Diagnostics.Trace;

namespace AddonNice.UI.WebControls
{
	/// <summary>
	/// The PortalCRMModuleControl class inherits from PortalModuleControl.
    /// It contains all CRM properties to manage dispay of modules in a CRM iFrame
    /// It contains methods to call directly CRMWrapper.
	/// </summary>
    public class PortalCRMModuleControl : PortalModuleControl
	{
        #region CRM privates
        
        // CRM Entity Name (schema)
        private string _EntityName              =   string.Empty;
        // Property to use as the displayed property by this module
        private string _EntityDisplayProperty   =   string.Empty;
        // Id for the request entity
        private Guid _entityID                  =   Guid.Empty;
        
        #endregion CRM

        #region Toolbox for CRM

        /// <summary>
        /// Return the static Wrapper stored in PortalSecurity
        /// </summary>
        protected CRMWrapperBase Wrapper
        {
            get
            {
                return AddonNice.Security.PortalSecurity.Wrapper;
            }
        }
		
        /// <summary>
        /// Used to ensure that the wrapper in any DynEntity object is the current one, as they go in cache they need to refresh their wrapper 
        /// </summary>
        protected virtual void ResetWrapper(DynEntity dynEnt)
        {
            CRMWrapperBase  w   =   Wrapper;
            if ( !dynEnt.HasWrapper(w) )
                dynEnt.SetWrapper(w);
        }

		/// <summary>
		/// Execute the request with the CRM logged user, the logged user maynot have enough privileges
		/// </summary>
        protected InternalResponse userExecute(InternalRequest req)
        {
            return internalExecute(req,false);
        }

        /// <summary>
		/// Execute the request with the CRM admin user, to be used when the logged user maynot have enough privileges
		/// </summary>
		protected InternalResponse adminExecute(InternalRequest req)
        {
            return internalExecute(req,true);
        }
		
		private InternalResponse internalExecute(InternalRequest req,bool isAdmin)
        {
			if ( isAdmin )
            	return AddonNice.Security.PortalSecurity.Wrapper.adminExecute(req);
            return AddonNice.Security.PortalSecurity.Wrapper.userExecute(req);
        }

        /// <summary>
        /// Retrieve the data columns specified for the entity corresponding to this guid, using the CRM logged user
		/// Retrieve if exists and if users has privilege to read this data
        /// </summary>
		protected InternalBusinessEntity userRetrieve(string typename, Guid Id, InternalColumnSetBase col)
        {
            return AddonNice.Security.PortalSecurity.Wrapper.Retrieve(typename, Id, col, false);
        }

        /// <summary>
        /// Retrieve the data columns specified for the entity corresponding to this guid, using the CRM admin user
		/// Always retrive if exists, beware thtathelogged user may not have rights to see this data
        /// </summary>
		protected InternalBusinessEntity adminRetrieve(string typename, Guid Id, InternalColumnSetBase col)
        {
            return AddonNice.Security.PortalSecurity.Wrapper.Retrieve(typename, Id, col, true);
        }

        /// <summary>
		/// Retrive all occurence of entities corresponding to this query and accessible to the logged user
		/// </summary>
        protected InternalBusinessEntityCollection userRetrieveMultiple(InternalQueryBase quer)
        {
            return AddonNice.Security.PortalSecurity.Wrapper.RetrieveMultiple(quer,false);
        }

        /// <summary>
        /// Retrieve all corresponding entities with adminuser, beware that the retrieved datas may not normally be accessible to the logged user
        /// </summary>
		protected InternalBusinessEntityCollection adminRetrieveMultiple(InternalQueryBase quer)
        {
            return AddonNice.Security.PortalSecurity.Wrapper.RetrieveMultiple(quer,true);
        }
 
		/// <summary>
		/// Delete with the logged user, must have corrsponding privilege
		/// </summary>
        protected void userDelete(string typename, Guid Id)
        {
            AddonNice.Security.PortalSecurity.Wrapper.Delete(typename, Id, false);
        }

        /// <summary>
        /// Delete bwith admin user, beware, always delete
        /// </summary>
		protected void adminDelete(string typename, Guid Id)
        {
            AddonNice.Security.PortalSecurity.Wrapper.Delete(typename, Id, true);
        }

		/// <summary>
		/// Update the selected entity with logged user account
		/// </summary>
        protected void userUpdate(InternalBusinessEntity bu)
        {
            AddonNice.Security.PortalSecurity.Wrapper.Update(bu, false);
        }

        /// <summary>
        /// Update with admin user, to be used when the log on user has no rights
		/// The created enty will be marked as modified by the admin
        /// </summary>
		protected void adminUpdate(InternalBusinessEntity bu)
        {
            AddonNice.Security.PortalSecurity.Wrapper.Update(bu,true);
        }

        /// <summary>
        /// Create with admin user, to be used when the log on user has no rights
		/// The created enty will belong to the logged usedr
        /// </summary>
        protected Guid userCreate(InternalBusinessEntity bu)
        {
            return AddonNice.Security.PortalSecurity.Wrapper.Create(bu, false);
        }

        /// <summary>
        /// Create with admin user, to be used when the log on user has no rights
		/// The created enty will belong to the admin, must be assigned to some other user later or by workflow
        /// </summary>
		protected Guid adminCreate(InternalBusinessEntity bu)
        {
            return AddonNice.Security.PortalSecurity.Wrapper.Create(bu, true);
        }

        /// <summary>
        /// Extract the text value from a piclist
        /// </summary>
        public string PickListData(string schemaName, string entite, int value)
        {
            return Wrapper.Util.PickListData(schemaName, entite, value);
        }

        /// <summary>
        /// Extract picklist values and insert them in an arraylist
        /// Contained object is a CrmListInt with 'name' and 'val' contents
        /// </summary>
        public ArrayList GetPickListArray(string picklistName,string entityName)
        {
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalCRMModuleControl GetPickListArray BEG picklistName: {0}, entityName: {1}",picklistName,entityName),ModuleTraceSwitch.Sw.Info);
            ArrayList arl   =   Wrapper.Util.ListFromPickList(picklistName,entityName);
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalCRMModuleControl GetPickListArray END Count: {0}",arl.Count),ModuleTraceSwitch.Sw.Info);
            return arl;
        }

        public string NewEntitySubArea(string id,string wentity,bool AvailableOffline,string Client)
        {
            string str  =   CrmUtil4SiteMap.NewEntitySubArea(id,wentity,AvailableOffline,Client);
            if (InstallTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalCRMModuleControl NewEntitySubArea: {0}",str),InstallTraceSwitch.Sw.Info);
            return str;
        }

        public string NewEntitySubAreaWithReadPrivileges(string id,string wentity,bool AvailableOffline,List<string> ReadPrivileges,string Client)
        {
            string str  =   CrmUtil4SiteMap.NewEntitySubAreaWithReadPrivileges(id,wentity,AvailableOffline,ReadPrivileges,Client);
            if (InstallTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalCRMModuleControl NewEntitySubAreaWithReadPrivileges: {0}",str),InstallTraceSwitch.Sw.Info);
            return str;
        }

        #endregion Toolbox for CRM

        #region Toolbox for Exchanging data with child pages using xml container

        /// <summary>
        /// Utility from Addon Nice : Given a key returns the value stored in an XML document usualy stored in DB
        /// </summary>
        /// <param name="MetadataXml">XmlDocument containing key value pairs in attributes</param>
        /// <param name="key">key of the pair</param>
        /// <returns>value</returns>
        protected string GetMetadata(object MetadataXml, string key)
        {
    		if ( ModuleTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalCRMModuleControl GetMetadata BEG key: {0}.",key),ModuleTraceSwitch.Sw.Info);
            XmlDocument Metadata = new XmlDocument();
            try
            {
                Metadata.LoadXml((string)MetadataXml);
            }
            catch (Exception ex)
            {
    		    if ( ModuleTraceSwitch.Sw.TraceError)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]PortalCRMModuleControl GetMetadata ex: {0}.",ex),ModuleTraceSwitch.Sw.Info);
                throw;
            }

            XmlNode targetNode = Metadata.SelectSingleNode("/Metadata/@" + key);
            if (targetNode == null)
            {
    		    if ( ModuleTraceSwitch.Sw.TraceVerbose )
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalCRMModuleControl GetMetadata key: {0} NOT FOUND.",key),ModuleTraceSwitch.Sw.Info);
                return null;
            }
		    if ( ModuleTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalCRMModuleControl GetMetadata value: {0}.",targetNode.Value),ModuleTraceSwitch.Sw.Info);
            return targetNode.Value;
        }

        protected string GetMetadata(XmlDocument Metadata,string key)
        {
            XmlNodeList lst     =   Metadata.GetElementsByTagName("Metadata");
    		if ( ModuleTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalCRMModuleControl GetMetadata from XmlDocument BEG key: {0}, count: {1}.",key,lst.Count),ModuleTraceSwitch.Sw.Info);
            if ( lst.Count == 0 )
                return null;
            XmlNode nd          =   lst[0];
            XmlAttribute at     =   nd.Attributes[key];
            if (at == null)
            {
                if (ModuleTraceSwitch.Sw.TraceVerbose)
                    Trace2.WriteLine("[V]PortalCRMModuleControl GetMetadata XmlAttribute NOT FOUND.", ModuleTraceSwitch.Sw.Info);
                return null;
            }
    		if ( ModuleTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalCRMModuleControl GetMetadata END key: {0}, Value: {1}.",key,at.Value),ModuleTraceSwitch.Sw.Info);
            return at.Value;
        }


        #endregion

        #region CRM properties

		public override bool ApplyLayout
		{
			get
			{
                if ( IsUnderCRM && portalSettings.NoLayoutUnderCrm )
                    return false;
                return Settings[StStr.ModuleSettingsApplyModuleLayout].ToBool();
			}
		}
        
        
        /// <summary>
        /// Custom Entity attached to this module by settings (stay in DB)
        /// Each occurence of a custom entity corresponds to a record in Addon Nice DB, 
        /// We can access this record using the EntityID passed by CRM in the iFrame
        /// </summary>
        public virtual string EntityName
        {
            get
            {
                if (string.IsNullOrEmpty(_EntityName))
                {
                    // if should use the page settings
                    if (_baseSettings[StStr.ModuleSettingsCRMDefault2PageEntityName].ToBool())
                    {
                        if ( portalSettings.ActivePageSettings.Settings.ContainsKeyNotEmpty(StStr.PageCRMEntityNameSettings) )
                            _EntityName =   portalSettings.ActivePageSettings.Settings[StStr.PageCRMEntityNameSettings ].Value;
                    }
                    // if still not assigned try to find in local module settings
                    if (string.IsNullOrEmpty(_EntityName) && _baseSettings.ContainsKey(StStr.ModuleSettingsCRMEntityNameSettings))
                        _EntityName = _baseSettings[StStr.ModuleSettingsCRMEntityNameSettings].Value;
                }
                return _EntityName;
            }
        }

        /// <summary>
        /// Property to use as the displayed property by this module
        /// </summary>
        public virtual string EntityDisplayProperty
        {
            get
            {
                if (string.IsNullOrEmpty(_EntityDisplayProperty))
                {
                    /* not imp
                    // if should use the page settings
                    if (_baseSettings[StStr.ModuleSettingsCRMDefault2PageEntityName].ToBool())
                    {
                        if ( portalSettings.ActivePageSettings.Settings.ContainsKeyNotEmpty(StStr.PageCRMEntityNameSettings) )
                            _EntityName =   portalSettings.ActivePageSettings.Settings[StStr.PageCRMEntityNameSettings ].Value;
                    }
                     * */
                    // if still not assigned try to find in local module settings
                    if (string.IsNullOrEmpty(_EntityDisplayProperty) && _baseSettings.ContainsKey(StStr.ModuleSettingsCRMEntityDisplayProperty))
                        _EntityDisplayProperty = _baseSettings[StStr.ModuleSettingsCRMEntityDisplayProperty].Value;
                }
                return _EntityDisplayProperty;
            }
        }

        /// <summary>
        /// Used to check the management mode
        /// </summary>
        public virtual bool InOwnCustomEntity
        {
            get
            {
                return EntityName == RequestEntityTypename;
            }
        }

        /// <summary>
        /// Is the module need to be attached to a CRM entity to work properly
        /// Default: true, to redefine if general usage crm module
        /// </summary>
        public virtual bool NeedAttachedEntity
        {
            get
            {
                return true;
            }
        }

        /// <summary>
        /// Is the module attached to a CRM custom entity
        /// </summary>
        public bool IsAttached
        {
            get
            {
                return !string.IsNullOrEmpty(EntityName);
            }
        }

        /// <summary>
        /// This is the current entity for which we have loaded the iFrame
		/// Value come from the request parameter 'id' sent by the CRM iFrame (dont forget to ask it to send the parameter)
        /// </summary>
        public Guid EntityID
        {
            get
            {
                if ( _entityID == Guid.Empty )
                    _entityID = Wrapper.RequestEntityID;
                return _entityID;
            }
        }

        public static string RequestEntityID
        {
            get
            {
                return CRMWrapperBase.RequestEntityIDStr;
            }
        }
        
        /// <summary>
        /// Crm sends the id query string with {} surounding the guid value, not AddonNice
        /// We use this to differenciate internal and external calls
        /// </summary>
        public bool IsCrmEntityID
        {
            get
            {
                return Wrapper.IsCrmEntityID;
            }
        }

        /// <summary>
        /// When in creation mode we have no entityID, this is the reason why
        /// We add a Crm marker in the iframe url /site/ucrm_1/PageId/xxx.aspx
        /// </summary>
        public bool RequestHasCrmMark
        {
            get
            {
                return Wrapper.RequestHasCrmMark;
            }
        }

        /// <summary>
        /// Get EntityType from parametres sent by CRM to the iFrame Field contaning our Module
        /// </summary>
        public string RequestEntityTypename
        {
            get
            {
                return Wrapper.RequestEntityTypename;
            }
        }

        public string RequestEntityTypeCode
        {
            get
            {
                return Wrapper.RequestEntityTypeCode;
            }
        }
    

        /// <summary>
        /// CRM V4
        /// Get the orgname sent by CRM iFrame as parameter
        /// Organization Name The unique name of the organization. 
        /// </summary>
        public virtual string RequestOrgName
        {
            get
            {
                return Wrapper.RequestOrgName;
            }
        }

        /// <summary>
        /// CRM V4
        /// User LCID sent in request string by CRM from v4, -1 when not initialized or v3
        /// </summary>
        public int RequestUserLCID
        {
            get
            {
                return Wrapper.RequestUserLCID;
            }
        }
        
		/// <summary>
		/// Test if CrmOrg LCID is a child of sent LCID
        /// Because DefLCID in DB is always a base language LCID
		/// </summary>
		public bool IsParentOfCrmOrgLCID(int LCID)
		{
            return Wrapper.IsParentOfCrmOrgLCID(LCID);
        }

        /// <summary>
        /// CRM V4
        /// Org LCID sent in request string by CRM from v4, -1 when not initialized or v3
        /// </summary>
        public int RequestOrgLCID
        {
            get
            {
                return Wrapper.RequestOrgLCID;
            }
        }
        
        
        /// <summary>
        /// CRM V4
        /// userlcid User Language Code The language code identifier that is used by the current user. 
        /// </summary>
        public virtual string RequestUserLCIDStr
        {
            get
            {
                return Wrapper.RequestUserLCIDStr;
            }
        }

        /// <summary>
        /// CRM V4
        /// orglcid Organization Language Code The language code identifier that represents the base language for the organization. 
        /// </summary>
        public virtual string RequestOrgLCIDStr
        {
            get
            {
                return Wrapper.RequestOrgLCIDStr;
            }
        }
        
        /// <summary>
        /// Is the module called from a CRM iFrame
        /// </summary>
        public virtual bool IsUnderCRM
        {
            get
            {
                return Wrapper.IsUnderCRM;
            }
        }

        public virtual bool IsInEntityCreationMode
        {
            get
            {
                return Wrapper.IsInEntityCreationMode;
            }
        }

        public bool CRMSimulation
        {
            get
            {
                return Wrapper.CRMSimulation;
            }
            set
            {
                Wrapper.CRMSimulation   =   value;
            }
        }

        public bool IsCRMSimulation
        {
            get
            {
                return CRMSimulation;
            }
        }

        #endregion CRM properties

		#region Constructor

		/// <summary>
		/// Default contructor, initializes default settings
		/// </summary>
		public PortalCRMModuleControl()
		{}
		
        #endregion

        public override void InitPortalModuleControl(ModuleSettingsDictionary bSettings)
        {
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine("[V]PortalModuleControl InitPortalModuleControl BEG.",ModuleTraceSwitch.Sw.Info);

            PortalModuleInitializer = new PortalCRMModuleControlSI(bSettings,this);
        }

            
        # region Install / Uninstall Implementation

        /// <summary>
        /// True when module depends from a list of custom entities, overrides to true 
        /// </summary>
        public virtual bool DependsFromCustomCrmEntities
        {
            get
            {
                return (RelatedCustomEntities != null) && (RelatedCustomEntities.Count > 0 );
            }
        }

        /// <summary>
        /// SortedLit of entities/version from which this module depends, schema name is the key, version is a string in the form major.minor
        /// </summary>
        public virtual SortedList<string,string> RelatedCustomEntities
        {
            get
            {
                return null;
            }
        }

        public virtual void UnInstallCrm(IDictionary stateSaver,bool backupCustomizations,bool publish)
        {
            if (DependsFromCustomCrmEntities)
            {
                SortedList<string,string> custEntities  =   RelatedCustomEntities;
                CrmDB CrmManDB                          =    new CrmDB();
                if ( InstallTraceSwitch.Sw.TraceVerbose )
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalCRMModuleControl UnInstallCrm Count: {0}", custEntities.Count),InstallTraceSwitch.Sw.Info);
                foreach(string schemaName in custEntities.Keys)
                {
                    string EVersion     =   custEntities[schemaName];
                    if ( !CrmManDB.ExistCrmEntity(schemaName,EVersion) )
                        continue;
                    DBCrmEntity entObj  =   CrmManDB.GetCrmEntityBySchemaNameObj(schemaName,EVersion); 
                    CrmManDB.DeleteModuleEntity(entObj.EntityId,GuidID);
                    if ( InstallTraceSwitch.Sw.TraceVerbose )
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalCRMModuleControl UnInstallCrm removed custom entity: {0}, version: {1}", schemaName,EVersion),InstallTraceSwitch.Sw.Info);
                }
            }
            if ( InstallTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine("[V]PortalCRMModuleControl UnInstallCrm END.",InstallTraceSwitch.Sw.Info);
        }

        /// <summary>
        /// Install any needed custom entity it depends on in Portal DB
        /// Called after Install,only when module has DependsFromCustomCrmEntities flag set 
        /// </summary>
        public virtual void InstallCrm(IDictionary stateSaver,bool upgrade)
        {
            if ( InstallTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalCRMModuleControl InstallCrm BEG Module : {0}, Guid: {1}", GetType().Name, GuidID),InstallTraceSwitch.Sw.Info);
            if (DependsFromCustomCrmEntities)
            {
                SortedList<string,string> custEntities  =   RelatedCustomEntities;
                CrmDB CrmManDB                          =    new CrmDB();
                if ( InstallTraceSwitch.Sw.TraceVerbose )
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalCRMModuleControl InstallCrm custom Count: {0}", custEntities.Count),InstallTraceSwitch.Sw.Info);
                foreach(string schemaName in custEntities.Keys)
                {
                    string EVersion                     =   custEntities[schemaName];
                    if ( !CrmManDB.ExistCrmEntity(schemaName,EVersion) )
                        continue;
                    DBCrmEntity entObj  =   CrmManDB.GetCrmEntityBySchemaNameObj(schemaName,EVersion); 
                    CrmManDB.AddModuleEntity(entObj.EntityId,GuidID);
                    if ( InstallTraceSwitch.Sw.TraceVerbose )
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalCRMModuleControl InstallCrm added custom entity: {0}, version: {1}", schemaName,EVersion),InstallTraceSwitch.Sw.Info);
                }
            }
            if ( InstallTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine("[V]PortalCRMModuleControl InstallCrm END.",InstallTraceSwitch.Sw.Info);
        }

        /// <summary>
        /// Do base install for module and do any CRM install needed
        /// </summary>
        public override void Install(IDictionary stateSaver,bool backupCustomizations,bool publish)
        {
            if ( InstallTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalCRMModuleControl Install BEG Module : {0}, Guid: {1}", GetType().Name, GuidID),InstallTraceSwitch.Sw.Info);
            base.Install(stateSaver,backupCustomizations,publish);
            if ( DependsFromCustomCrmEntities )
                InstallCrm(stateSaver,false);
            if ( InstallTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalCRMModuleControl Install END Installed Module : {0}, Guid: {1}", GetType().Name, GuidID),InstallTraceSwitch.Sw.Info);
        }

        /// <summary>
        /// Do base install for module and do any CRM install needed
        /// </summary>
        public override void ReInstall(IDictionary stateSaver,bool backupCustomizations,bool publish)
        {
            if ( InstallTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalCRMModuleControl Install BEG Module : {0}, Guid: {1}", GetType().Name, GuidID),InstallTraceSwitch.Sw.Info);
            base.ReInstall(stateSaver,backupCustomizations,publish);
            if ( DependsFromCustomCrmEntities )
                InstallCrm(stateSaver,true);
            if ( InstallTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalCRMModuleControl Install END Installed Module : {0}, Guid: {1}", GetType().Name, GuidID),InstallTraceSwitch.Sw.Info);
        }

        /// <summary>
        /// Do base uninstall of module then any crm entity delete
        /// </summary>
        public override void Uninstall(IDictionary stateSaver,bool backupCustomizations,bool publish)
        {
            if ( InstallTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalCRMModuleControl Uninstall Uninstalling Module : {0}, Guid: {1}", GetType().Name, GuidID),InstallTraceSwitch.Sw.Info);
            base.Uninstall(stateSaver,backupCustomizations,publish);
            if ( DependsFromCustomCrmEntities )
                UnInstallCrm(stateSaver,backupCustomizations,publish);
            if ( InstallTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalCRMModuleControl Uninstalled Module : {0}, Guid: {1}", GetType().Name, GuidID),InstallTraceSwitch.Sw.Info);
        }

        #endregion

        #region overrides

        /// <summary>
        /// All modules under PortalCRMModule will receive the Crm category as a default
        /// </summary>
        public override string Category
		{
			get
			{
                return StStr.CrmModuleCat;
			}
		}

		public override string CategoryName
		{
			get
			{
                return LocalizeHelper.Localize(StStr.CRM_MOD_CAT,StStr.CrmModuleCat);
			}
		}
        
        /// <summary>
        /// -> change 6/09 CS seems bad:Permission for AddButton: if not undercrm and not attached or under crm in creation allow add button
        /// Permission for AddButton: 
        /// When under CRm we can add only if the entity is created
        /// When not underCrm we need some entity name so we need to be attached to create
        /// </summary>
        public override bool CanAdd
        {
            get
            {
                bool ret    =   false;
                if ( IsUnderCRM ) 
                {
                    if ( !IsInEntityCreationMode )
                        ret =   base.CanAdd;
                }
                else if ( !NeedAttachedEntity || IsAttached )
                     ret    =   base.CanAdd;
                if ( ModuleTraceSwitch.Sw.TraceVerbose )
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalCRMModuleControl CanAdd ModuleId: {0}, CanAdd: {1}", ModuleID, ret),ModuleTraceSwitch.Sw.Info);
                return ret;
            }
        }

        /// <summary>
        /// We insert the javascript that will allow to trap the save or Save and close button
        /// </summary>
        protected override void OnLoad(EventArgs e)
        {
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalCRMModuleControl OnLoad BEG ModuleID: {0}", ModuleID),ModuleTraceSwitch.Sw.Info);
            // first let-s create the buttons
            base.OnLoad(e);
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalCRMModuleControl OnLoad END ModuleID: {0}", ModuleID),ModuleTraceSwitch.Sw.Info);
        }
        #endregion
    }
}
